home *** CD-ROM | disk | FTP | other *** search
/ Aminet 49 / Aminet 49 (2002)(GTI - Schatztruhe)[!][Jun 2002].iso / Aminet / util / libs / ttrender.lha / ttrender-2.0 / Developer / source / base / ftobjs.c < prev    next >
Encoding:
C/C++ Source or Header  |  2002-04-06  |  73.9 KB  |  2,787 lines

  1. /***************************************************************************/
  2. /*                                                                         */
  3. /*  ftobjs.c                                                               */
  4. /*                                                                         */
  5. /*    The FreeType private base classes (body).                            */
  6. /*                                                                         */
  7. /*  Copyright 1996-2001 by                                                 */
  8. /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
  9. /*                                                                         */
  10. /*  This file is part of the FreeType project, and may only be used,       */
  11. /*  modified, and distributed under the terms of the FreeType project      */
  12. /*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
  13. /*  this file you indicate that you have read the license and              */
  14. /*  understand and accept it fully.                                        */
  15. /*                                                                         */
  16. /***************************************************************************/
  17.  
  18.  
  19. #include <ft2build.h>
  20. #include FT_LIST_H
  21. #include FT_OUTLINE_H
  22. #include FT_INTERNAL_OBJECTS_H
  23. #include FT_INTERNAL_DEBUG_H
  24. #include FT_INTERNAL_STREAM_H
  25. #include FT_TRUETYPE_TABLES_H
  26. #include FT_OUTLINE_H
  27.  
  28. #include <string.h>     /* for strcmp() */
  29.  
  30.  
  31.   /*************************************************************************/
  32.   /*************************************************************************/
  33.   /*************************************************************************/
  34.   /****                                                                 ****/
  35.   /****                                                                 ****/
  36.   /****                           M E M O R Y                           ****/
  37.   /****                                                                 ****/
  38.   /****                                                                 ****/
  39.   /*************************************************************************/
  40.   /*************************************************************************/
  41.   /*************************************************************************/
  42.  
  43.   /*************************************************************************/
  44.   /*                                                                       */
  45.   /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
  46.   /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
  47.   /* messages during execution.                                            */
  48.   /*                                                                       */
  49. #undef  FT_COMPONENT
  50. #define FT_COMPONENT  trace_memory
  51.  
  52.  
  53.   /* documentation is in ftmemory.h */
  54.  
  55.   FT_BASE_DEF( FT_Error )
  56.   FT_Alloc( FT_Memory  memory,
  57.             FT_Long    size,
  58.             void*     *P )
  59.   {
  60.     FT_Assert( P != 0 );
  61.  
  62.     if ( size > 0 )
  63.     {
  64.       *P = memory->alloc( memory, size );
  65.       if ( !*P )
  66.       {
  67.         FT_ERROR(( "FT_Alloc:" ));
  68.         FT_ERROR(( " Out of memory? (%ld requested)\n",
  69.                    size ));
  70.  
  71.         return FT_Err_Out_Of_Memory;
  72.       }
  73.       MEM_Set( *P, 0, size );
  74.     }
  75.     else
  76.       *P = NULL;
  77.  
  78.     FT_TRACE7(( "FT_Alloc:" ));
  79.     FT_TRACE7(( " size = %ld, block = 0x%08p, ref = 0x%08p\n",
  80.                 size, *P, P ));
  81.  
  82.     return FT_Err_Ok;
  83.   }
  84.  
  85.  
  86.   /* documentation is in ftmemory.h */
  87.  
  88.   FT_BASE_DEF( FT_Error )
  89.   FT_Realloc( FT_Memory  memory,
  90.               FT_Long    current,
  91.               FT_Long    size,
  92.               void**     P )
  93.   {
  94.     void*  Q;
  95.  
  96.  
  97.     FT_Assert( P != 0 );
  98.  
  99.     /* if the original pointer is NULL, call FT_Alloc() */
  100.     if ( !*P )
  101.       return FT_Alloc( memory, size, P );
  102.  
  103.     /* if the new block if zero-sized, clear the current one */
  104.     if ( size <= 0 )
  105.     {
  106.       FT_Free( memory, P );
  107.       return FT_Err_Ok;
  108.     }
  109.  
  110.     Q = memory->realloc( memory, current, size, *P );
  111.     if ( !Q )
  112.       goto Fail;
  113.  
  114.     if ( size > current )
  115.       MEM_Set( (char*)Q + current, 0, size - current );
  116.  
  117.     *P = Q;
  118.     return FT_Err_Ok;
  119.  
  120.   Fail:
  121.     FT_ERROR(( "FT_Realloc:" ));
  122.     FT_ERROR(( " Failed (current %ld, requested %ld)\n",
  123.                current, size ));
  124.     return FT_Err_Out_Of_Memory;
  125.   }
  126.  
  127.  
  128.   /* documentation is in ftmemory.h */
  129.  
  130.   FT_BASE_DEF( void )
  131.   FT_Free( FT_Memory  memory,
  132.            void**     P )
  133.   {
  134.     FT_TRACE7(( "FT_Free:" ));
  135.     FT_TRACE7(( " Freeing block 0x%08p, ref 0x%08p\n",
  136.                 P, P ? *P : (void*)0 ));
  137.  
  138.     if ( P && *P )
  139.     {
  140.       memory->free( memory, *P );
  141.       *P = 0;
  142.     }
  143.   }
  144.  
  145.  
  146.   /*************************************************************************/
  147.   /*************************************************************************/
  148.   /*************************************************************************/
  149.   /****                                                                 ****/
  150.   /****                                                                 ****/
  151.   /****                           S T R E A M                           ****/
  152.   /****                                                                 ****/
  153.   /****                                                                 ****/
  154.   /*************************************************************************/
  155.   /*************************************************************************/
  156.   /*************************************************************************/
  157.  
  158.  
  159.   /*************************************************************************/
  160.   /*                                                                       */
  161.   /* <Function>                                                            */
  162.   /*    ft_new_input_stream                                                */
  163.   /*                                                                       */
  164.   /* <Description>                                                         */
  165.   /*    Creates a new input stream object from an FT_Open_Args structure.  */
  166.   /*                                                                       */
  167.   /* <Note>                                                                */
  168.   /*    The function expects a valid `astream' parameter.                  */
  169.   /*                                                                       */
  170.   static FT_Error
  171.   ft_new_input_stream( FT_Library     library,
  172.                        FT_Open_Args*  args,
  173.                        FT_Stream*     astream )
  174.   {
  175.     FT_Error   error;
  176.     FT_Memory  memory;
  177.     FT_Stream  stream;
  178.  
  179.  
  180.     if ( !library )
  181.       return FT_Err_Invalid_Library_Handle;
  182.  
  183.     if ( !args )
  184.       return FT_Err_Invalid_Argument;
  185.  
  186.     *astream = 0;
  187.     memory   = library->memory;
  188.     if ( ALLOC( stream, sizeof ( *stream ) ) )
  189.       goto Exit;
  190.  
  191.     stream->memory = memory;
  192.  
  193.     /* now, look at the stream flags */
  194.     if ( args->flags & ft_open_memory )
  195.     {
  196.       error = 0;
  197.       FT_New_Memory_Stream( library,
  198.                             (FT_Byte*)args->memory_base,
  199.                             args->memory_size,
  200.                             stream );
  201.     }
  202.     else if ( args->flags & ft_open_pathname )
  203.     {
  204.       error = FT_New_Stream( args->pathname, stream );
  205.       stream->pathname.pointer = args->pathname;
  206.     }
  207.     else if ( ( args->flags & ft_open_stream ) && args->stream )
  208.     {
  209.       /* in this case, we do not need to allocate a new stream object */
  210.       /* since the caller is responsible for closing it himself       */
  211.       FREE( stream );
  212.       stream = args->stream;
  213.     }
  214.     else
  215.       error = FT_Err_Invalid_Argument;
  216.  
  217.     if ( error )
  218.       FREE( stream );
  219.  
  220.     *astream = stream;
  221.  
  222.   Exit:
  223.     return error;
  224.   }
  225.  
  226.  
  227.   /* documentation is in ftobjs.h */
  228.  
  229.   FT_EXPORT_DEF( void )
  230.   FT_Done_Stream( FT_Stream  stream )
  231.   {
  232.     if ( stream && stream->close )
  233.     {
  234.       stream->close( stream );
  235.       stream->close = 0;
  236.     }
  237.   }
  238.  
  239.  
  240.   static void
  241.   ft_done_stream( FT_Stream*  astream,
  242.                   FT_Int      external )
  243.   {
  244.     FT_Stream  stream = *astream;
  245.  
  246.  
  247.     if ( stream->close )
  248.       stream->close( stream );
  249.  
  250.     if ( !external )
  251.     {
  252.       FT_Memory  memory = stream->memory;
  253.  
  254.  
  255.       FREE( stream );
  256.     }
  257.     *astream = 0;
  258.   }
  259.  
  260.  
  261. #undef  FT_COMPONENT
  262. #define FT_COMPONENT  trace_objs
  263.  
  264.  
  265.   /*************************************************************************/
  266.   /*************************************************************************/
  267.   /*************************************************************************/
  268.   /****                                                                 ****/
  269.   /****                                                                 ****/
  270.   /****                     G L Y P H   L O A D E R                     ****/
  271.   /****                                                                 ****/
  272.   /****                                                                 ****/
  273.   /*************************************************************************/
  274.   /*************************************************************************/
  275.   /*************************************************************************/
  276.  
  277.  
  278.   /*************************************************************************/
  279.   /*                                                                       */
  280.   /* The glyph loader is a simple object which is used to load a set of    */
  281.   /* glyphs easily.  It is critical for the correct loading of composites. */
  282.   /*                                                                       */
  283.   /* Ideally, one can see it as a stack of abstract `glyph' objects.       */
  284.   /*                                                                       */
  285.   /*   loader.base     Is really the bottom of the stack.  It describes a  */
  286.   /*                   single glyph image made of the juxtaposition of     */
  287.   /*                   several glyphs (those `in the stack').              */
  288.   /*                                                                       */
  289.   /*   loader.current  Describes the top of the stack, on which a new      */
  290.   /*                   glyph can be loaded.                                */
  291.   /*                                                                       */
  292.   /*   Rewind          Clears the stack.                                   */
  293.   /*   Prepare         Set up `loader.current' for addition of a new glyph */
  294.   /*                   image.                                              */
  295.   /*   Add             Add the `current' glyph image to the `base' one,    */
  296.   /*                   and prepare for another one.                        */
  297.   /*                                                                       */
  298.   /* The glyph loader is now a base object.  Each driver used to           */
  299.   /* re-implement it in one way or the other, which wasted code and        */
  300.   /* energy.                                                               */
  301.   /*                                                                       */
  302.   /*************************************************************************/
  303.  
  304.  
  305.   /* create a new glyph loader */
  306.   FT_BASE_DEF( FT_Error )
  307.   FT_GlyphLoader_New( FT_Memory         memory,
  308.                       FT_GlyphLoader*  *aloader )
  309.   {
  310.     FT_GlyphLoader*  loader;
  311.     FT_Error         error;
  312.  
  313.  
  314.     if ( !ALLOC( loader, sizeof ( *loader ) ) )
  315.     {
  316.       loader->memory = memory;
  317.       *aloader       = loader;
  318.     }
  319.     return error;
  320.   }
  321.  
  322.  
  323.   /* rewind the glyph loader - reset counters to 0 */
  324.   FT_BASE_DEF( void )
  325.   FT_GlyphLoader_Rewind( FT_GlyphLoader*  loader )
  326.   {
  327.     FT_GlyphLoad*  base    = &loader->base;
  328.     FT_GlyphLoad*  current = &loader->current;
  329.  
  330.  
  331.     base->outline.n_points   = 0;
  332.     base->outline.n_contours = 0;
  333.     base->num_subglyphs      = 0;
  334.  
  335.     *current = *base;
  336.   }
  337.  
  338.  
  339.   /* reset the glyph loader, frees all allocated tables */
  340.   /* and starts from zero                               */
  341.   FT_BASE_DEF( void )
  342.   FT_GlyphLoader_Reset( FT_GlyphLoader*  loader )
  343.   {
  344.     FT_Memory memory = loader->memory;
  345.  
  346.  
  347.     FREE( loader->base.outline.points );
  348.     FREE( loader->base.outline.tags );
  349.     FREE( loader->base.outline.contours );
  350.     FREE( loader->base.extra_points );
  351.     FREE( loader->base.subglyphs );
  352.  
  353.     loader->max_points    = 0;
  354.     loader->max_contours  = 0;
  355.     loader->max_subglyphs = 0;
  356.  
  357.     FT_GlyphLoader_Rewind( loader );
  358.   }
  359.  
  360.  
  361.   /* delete a glyph loader */
  362.   FT_BASE_DEF( void )
  363.   FT_GlyphLoader_Done( FT_GlyphLoader*  loader )
  364.   {
  365.     if ( loader )
  366.     {
  367.       FT_Memory memory = loader->memory;
  368.  
  369.  
  370.       FT_GlyphLoader_Reset( loader );
  371.       FREE( loader );
  372.     }
  373.   }
  374.  
  375.  
  376.   /* re-adjust the `current' outline fields */
  377.   static void
  378.   FT_GlyphLoader_Adjust_Points( FT_GlyphLoader*  loader )
  379.   {
  380.     FT_Outline*  base    = &loader->base.outline;
  381.     FT_Outline*  current = &loader->current.outline;
  382.  
  383.  
  384.     current->points   = base->points   + base->n_points;
  385.     current->tags     = base->tags     + base->n_points;
  386.     current->contours = base->contours + base->n_contours;
  387.  
  388.     /* handle extra points table - if any */
  389.     if ( loader->use_extra )
  390.       loader->current.extra_points =
  391.         loader->base.extra_points + base->n_points;
  392.   }
  393.  
  394.  
  395.   FT_BASE_DEF( FT_Error )
  396.   FT_GlyphLoader_Create_Extra( FT_GlyphLoader*  loader )
  397.   {
  398.     FT_Error   error;
  399.     FT_Memory  memory = loader->memory;
  400.  
  401.  
  402.     if ( !ALLOC_ARRAY( loader->base.extra_points,
  403.                        loader->max_points, FT_Vector ) )
  404.     {
  405.       loader->use_extra = 1;
  406.       FT_GlyphLoader_Adjust_Points( loader );
  407.     }
  408.     return error;
  409.   }
  410.  
  411.  
  412.   /* re-adjust the `current' subglyphs field */
  413.   static void
  414.   FT_GlyphLoader_Adjust_Subglyphs( FT_GlyphLoader*  loader )
  415.   {
  416.     FT_GlyphLoad* base    = &loader->base;
  417.     FT_GlyphLoad* current = &loader->current;
  418.  
  419.  
  420.     current->subglyphs = base->subglyphs + base->num_subglyphs;
  421.   }
  422.  
  423.  
  424.   /* Ensure that we can add `n_points' and `n_contours' to our glyph. this */
  425.   /* function reallocates its outline tables if necessary.  Note that it   */
  426.   /* DOESN'T change the number of points within the loader!                */
  427.   /*                                                                       */
  428.   FT_BASE_DEF( FT_Error )
  429.   FT_GlyphLoader_Check_Points( FT_GlyphLoader*  loader,
  430.                                FT_UInt          n_points,
  431.                                FT_UInt          n_contours )
  432.   {
  433.     FT_Memory    memory  = loader->memory;
  434.     FT_Error     error   = FT_Err_Ok;
  435.     FT_Outline*  base    = &loader->base.outline;
  436.     FT_Outline*  current = &loader->current.outline;
  437.     FT_Bool      adjust  = 1;
  438.  
  439.     FT_UInt      new_max, old_max;
  440.  
  441.  
  442.     /* check points & tags */
  443.     new_max = base->n_points + current->n_points + n_points;
  444.     old_max = loader->max_points;
  445.  
  446.     if ( new_max > old_max )
  447.     {
  448.       new_max = ( new_max + 7 ) & -8;
  449.  
  450.       if ( REALLOC_ARRAY( base->points, old_max, new_max, FT_Vector ) ||
  451.            REALLOC_ARRAY( base->tags,   old_max, new_max, FT_Byte   ) )
  452.        goto Exit;
  453.  
  454.       if ( loader->use_extra &&
  455.            REALLOC_ARRAY( loader->base.extra_points, old_max,
  456.                           new_max, FT_Vector ) )
  457.        goto Exit;
  458.  
  459.       adjust = 1;
  460.       loader->max_points = new_max;
  461.     }
  462.  
  463.     /* check contours */
  464.     old_max = loader->max_contours;
  465.     new_max = base->n_contours + current->n_contours +
  466.               n_contours;
  467.     if ( new_max > old_max )
  468.     {
  469.       new_max = ( new_max + 3 ) & -4;
  470.       if ( REALLOC_ARRAY( base->contours, old_max, new_max, FT_Short ) )
  471.         goto Exit;
  472.  
  473.       adjust = 1;
  474.       loader->max_contours = new_max;
  475.     }
  476.  
  477.     if ( adjust )
  478.       FT_GlyphLoader_Adjust_Points( loader );
  479.  
  480.   Exit:
  481.     return error;
  482.   }
  483.  
  484.  
  485.   /* Ensure that we can add `n_subglyphs' to our glyph. this function */
  486.   /* reallocates its subglyphs table if necessary.  Note that it DOES */
  487.   /* NOT change the number of subglyphs within the loader!            */
  488.   /*                                                                  */
  489.   FT_BASE_DEF( FT_Error )
  490.   FT_GlyphLoader_Check_Subglyphs( FT_GlyphLoader*  loader,
  491.                                   FT_UInt          n_subs )
  492.   {
  493.     FT_Memory  memory = loader->memory;
  494.     FT_Error   error  = FT_Err_Ok;
  495.     FT_UInt    new_max, old_max;
  496.  
  497.     FT_GlyphLoad*  base    = &loader->base;
  498.     FT_GlyphLoad*  current = &loader->current;
  499.  
  500.  
  501.     new_max = base->num_subglyphs + current->num_subglyphs + n_subs;
  502.     old_max = loader->max_subglyphs;
  503.     if ( new_max > old_max )
  504.     {
  505.       new_max = ( new_max + 1 ) & -2;
  506.       if ( REALLOC_ARRAY( base->subglyphs, old_max, new_max, FT_SubGlyph ) )
  507.         goto Exit;
  508.  
  509.       loader->max_subglyphs = new_max;
  510.  
  511.       FT_GlyphLoader_Adjust_Subglyphs( loader );
  512.     }
  513.  
  514.   Exit:
  515.     return error;
  516.   }
  517.  
  518.  
  519.   /* prepare loader for the addition of a new glyph on top of the base one */
  520.   FT_BASE_DEF( void )
  521.   FT_GlyphLoader_Prepare( FT_GlyphLoader*  loader )
  522.   {
  523.     FT_GlyphLoad*  current = &loader->current;
  524.  
  525.  
  526.     current->outline.n_points   = 0;
  527.     current->outline.n_contours = 0;
  528.     current->num_subglyphs      = 0;
  529.  
  530.     FT_GlyphLoader_Adjust_Points   ( loader );
  531.     FT_GlyphLoader_Adjust_Subglyphs( loader );
  532.   }
  533.  
  534.  
  535.   /* add current glyph to the base image - and prepare for another */
  536.   FT_BASE_DEF( void )
  537.   FT_GlyphLoader_Add( FT_GlyphLoader*  loader )
  538.   {
  539.     FT_GlyphLoad*  base    = &loader->base;
  540.     FT_GlyphLoad*  current = &loader->current;
  541.  
  542.     FT_UInt        n_curr_contours = current->outline.n_contours;
  543.     FT_UInt        n_base_points   = base->outline.n_points;
  544.     FT_UInt        n;
  545.  
  546.  
  547.     base->outline.n_points =
  548.       (short)( base->outline.n_points + current->outline.n_points );
  549.     base->outline.n_contours =
  550.       (short)( base->outline.n_contours + current->outline.n_contours );
  551.  
  552.     base->num_subglyphs += current->num_subglyphs;
  553.  
  554.     /* adjust contours count in newest outline */
  555.     for ( n = 0; n < n_curr_contours; n++ )
  556.       current->outline.contours[n] =
  557.         (short)( current->outline.contours[n] + n_base_points );
  558.  
  559.     /* prepare for another new glyph image */
  560.     FT_GlyphLoader_Prepare( loader );
  561.   }
  562.  
  563.  
  564.   FT_BASE_DEF( FT_Error )
  565.   FT_GlyphLoader_Copy_Points( FT_GlyphLoader*  target,
  566.                               FT_GlyphLoader*  source )
  567.   {
  568.     FT_Error  error;
  569.     FT_UInt   num_points   = source->base.outline.n_points;
  570.     FT_UInt   num_contours = source->base.outline.n_contours;
  571.  
  572.  
  573.     error = FT_GlyphLoader_Check_Points( target, num_points, num_contours );
  574.     if ( !error )
  575.     {
  576.       FT_Outline*  out = &target->base.outline;
  577.       FT_Outline*  in  = &source->base.outline;
  578.  
  579.  
  580.       MEM_Copy( out->points, in->points,
  581.                 num_points * sizeof ( FT_Vector ) );
  582.       MEM_Copy( out->tags, in->tags,
  583.                 num_points * sizeof ( char ) );
  584.       MEM_Copy( out->contours, in->contours,
  585.                 num_contours * sizeof ( short ) );
  586.  
  587.       /* do we need to copy the extra points? */
  588.       if ( target->use_extra && source->use_extra )
  589.         MEM_Copy( target->base.extra_points, source->base.extra_points,
  590.                   num_points * sizeof ( FT_Vector ) );
  591.  
  592.       out->n_points   = (short)num_points;
  593.       out->n_contours = (short)num_contours;
  594.  
  595.       FT_GlyphLoader_Adjust_Points( target );
  596.     }
  597.  
  598.     return error;
  599.   }
  600.  
  601.  
  602.   /*************************************************************************/
  603.   /*************************************************************************/
  604.   /*************************************************************************/
  605.   /****                                                                 ****/
  606.   /****                                                                 ****/
  607.   /****               FACE, SIZE & GLYPH SLOT OBJECTS                   ****/
  608.   /****                                                                 ****/
  609.   /****                                                                 ****/
  610.   /*************************************************************************/
  611.   /*************************************************************************/
  612.   /*************************************************************************/
  613.  
  614.  
  615.   static FT_Error
  616.   ft_glyphslot_init( FT_GlyphSlot  slot )
  617.   {
  618.     FT_Driver         driver = slot->face->driver;
  619.     FT_Driver_Class*  clazz  = driver->clazz;
  620.     FT_Memory         memory = driver->root.memory;
  621.     FT_Error          error  = FT_Err_Ok;
  622.     FT_Slot_Internal  internal;
  623.  
  624.  
  625.     slot->library = driver->root.library;
  626.  
  627.     if ( ALLOC( internal, sizeof ( *internal ) ) )
  628.       goto Exit;
  629.  
  630.     slot->internal = internal;
  631.  
  632.     if ( FT_DRIVER_USES_OUTLINES( driver ) )
  633.       error = FT_GlyphLoader_New( memory, &internal->loader );
  634.  
  635.     if ( !error && clazz->init_slot )
  636.       error = clazz->init_slot( slot );
  637.  
  638.   Exit:
  639.     return error;
  640.   }
  641.  
  642.  
  643.   static void
  644.   ft_glyphslot_clear( FT_GlyphSlot  slot )
  645.   {
  646.     /* free bitmap if needed */
  647.     if ( slot->flags & ft_glyph_own_bitmap )
  648.     {
  649.       FT_Memory  memory = FT_FACE_MEMORY( slot->face );
  650.  
  651.  
  652.       FREE( slot->bitmap.buffer );
  653.       slot->flags &= ~ft_glyph_own_bitmap;
  654.     }
  655.  
  656.     /* clear all public fields in the glyph slot */
  657.     MEM_Set( &slot->metrics, 0, sizeof ( slot->metrics ) );
  658.     MEM_Set( &slot->outline, 0, sizeof ( slot->outline ) );
  659.     MEM_Set( &slot->bitmap,  0, sizeof ( slot->bitmap )  );
  660.  
  661.     slot->bitmap_left   = 0;
  662.     slot->bitmap_top    = 0;
  663.     slot->num_subglyphs = 0;
  664.     slot->subglyphs     = 0;
  665.     slot->control_data  = 0;
  666.     slot->control_len   = 0;
  667.     slot->other         = 0;
  668.     slot->format        = ft_glyph_format_none;
  669.  
  670.     slot->linearHoriAdvance = 0;
  671.     slot->linearVertAdvance = 0;
  672.   }
  673.  
  674.  
  675.   static void
  676.   ft_glyphslot_done( FT_GlyphSlot  slot )
  677.   {
  678.     FT_Driver         driver = slot->face->driver;
  679.     FT_Driver_Class*  clazz  = driver->clazz;
  680.     FT_Memory         memory = driver->root.memory;
  681.  
  682.  
  683.     if ( clazz->done_slot )
  684.       clazz->done_slot( slot );
  685.  
  686.     /* free bitmap buffer if needed */
  687.     if ( slot->flags & ft_glyph_own_bitmap )
  688.       FREE( slot->bitmap.buffer );
  689.  
  690.     /* free glyph loader */
  691.     if ( FT_DRIVER_USES_OUTLINES( driver ) )
  692.     {
  693.       FT_GlyphLoader_Done( slot->internal->loader );
  694.       slot->internal->loader = 0;
  695.     }
  696.  
  697.     FREE( slot->internal );
  698.   }
  699.  
  700.  
  701.   /* documentation is in ftobjs.h */
  702.  
  703.   FT_BASE_DEF( FT_Error )
  704.   FT_New_GlyphSlot( FT_Face        face,
  705.                     FT_GlyphSlot  *aslot )
  706.   {
  707.     FT_Error          error;
  708.     FT_Driver         driver;
  709.     FT_Driver_Class*  clazz;
  710.     FT_Memory         memory;
  711.     FT_GlyphSlot      slot;
  712.  
  713.  
  714.     if ( !face || !aslot || !face->driver )
  715.       return FT_Err_Invalid_Argument;
  716.  
  717.     *aslot = 0;
  718.  
  719.     driver = face->driver;
  720.     clazz  = driver->clazz;
  721.     memory = driver->root.memory;
  722.  
  723.     FT_TRACE4(( "FT_New_GlyphSlot: Creating new slot object\n" ));
  724.     if ( !ALLOC( slot, clazz->slot_object_size ) )
  725.     {
  726.       slot->face = face;
  727.  
  728.       error = ft_glyphslot_init( slot );
  729.       if ( error )
  730.       {
  731.         ft_glyphslot_done( slot );
  732.         FREE( slot );
  733.         goto Exit;
  734.       }
  735.  
  736.       *aslot = slot;
  737.     }
  738.  
  739.   Exit:
  740.     FT_TRACE4(( "FT_New_GlyphSlot: Return %d\n", error ));
  741.     return error;
  742.   }
  743.  
  744.  
  745.   /* documentation is in ftobjs.h */
  746.  
  747.   FT_BASE_DEF( void )
  748.   FT_Done_GlyphSlot( FT_GlyphSlot  slot )
  749.   {
  750.     if ( slot )
  751.     {
  752.       FT_Driver         driver = slot->face->driver;
  753.       FT_Memory         memory = driver->root.memory;
  754.       FT_GlyphSlot*     parent;
  755.       FT_GlyphSlot      cur;
  756.  
  757.  
  758.       /* Remove slot from its parent face's list */
  759.       parent = &slot->face->glyph;
  760.       cur    = *parent;
  761.  
  762.       while ( cur )
  763.       {
  764.         if ( cur == slot )
  765.         {
  766.           *parent = cur->next;
  767.           ft_glyphslot_done( slot );
  768.           FREE( slot );
  769.           break;
  770.         }
  771.         cur = cur->next;
  772.       }
  773.     }
  774.   }
  775.  
  776.  
  777.   /* documentation is in freetype.h */
  778.  
  779.   FT_EXPORT_DEF( void )
  780.   FT_Set_Transform( FT_Face     face,
  781.                     FT_Matrix*  matrix,
  782.                     FT_Vector*  delta )
  783.   {
  784.     FT_Face_Internal  internal;
  785.  
  786.  
  787.     if ( !face )
  788.       return;
  789.  
  790.     internal = face->internal;
  791.  
  792.     internal->transform_flags = 0;
  793.  
  794.     if ( !matrix )
  795.     {
  796.       internal->transform_matrix.xx = 0x10000L;
  797.       internal->transform_matrix.xy = 0;
  798.       internal->transform_matrix.yx = 0;
  799.       internal->transform_matrix.yy = 0x10000L;
  800.       matrix = &internal->transform_matrix;
  801.     }
  802.     else
  803.       internal->transform_matrix = *matrix;
  804.  
  805.     /* set transform_flags bit flag 0 if `matrix' isn't the identity */
  806.     if ( ( matrix->xy | matrix->yx ) ||
  807.          matrix->xx != 0x10000L      ||
  808.          matrix->yy != 0x10000L      )
  809.       internal->transform_flags |= 1;
  810.  
  811.     if ( !delta )
  812.     {
  813.       internal->transform_delta.x = 0;
  814.       internal->transform_delta.y = 0;
  815.       delta = &internal->transform_delta;
  816.     }
  817.     else
  818.       internal->transform_delta = *delta;
  819.  
  820.     /* set transform_flags bit flag 1 if `delta' isn't the null vector */
  821.     if ( delta->x | delta->y )
  822.       internal->transform_flags |= 2;
  823.   }
  824.  
  825.  
  826.   static FT_Renderer
  827.   ft_lookup_glyph_renderer( FT_GlyphSlot  slot );
  828.  
  829.  
  830.   /* documentation is in freetype.h */
  831.  
  832.   FT_EXPORT_DEF( FT_Error )
  833.   FT_Load_Glyph( FT_Face  face,
  834.                  FT_UInt  glyph_index,
  835.                  FT_Int   load_flags )
  836.   {
  837.     FT_Error      error;
  838.     FT_Driver     driver;
  839.     FT_GlyphSlot  slot;
  840.     FT_Library    library;
  841.     FT_Bool       autohint;
  842.     FT_Module     hinter;
  843.  
  844.  
  845.     if ( !face || !face->size || !face->glyph )
  846.       return FT_Err_Invalid_Face_Handle;
  847.  
  848.     if ( glyph_index >= (FT_UInt)face->num_glyphs )
  849.       return FT_Err_Invalid_Argument;
  850.  
  851.     slot = face->glyph;
  852.     ft_glyphslot_clear( slot );
  853.  
  854.     driver = face->driver;
  855.  
  856.     /* if the flag NO_RECURSE is set, we disable hinting and scaling */
  857.     if ( load_flags & FT_LOAD_NO_RECURSE )
  858.     {
  859.       /* disable scaling, hinting, and transformation */
  860.       load_flags |= FT_LOAD_NO_SCALE         |
  861.                     FT_LOAD_NO_HINTING       |
  862.                     FT_LOAD_IGNORE_TRANSFORM;
  863.  
  864.       /* disable bitmap rendering */
  865.       load_flags &= ~FT_LOAD_RENDER;
  866.     }
  867.  
  868.     /* do we need to load the glyph through the auto-hinter? */
  869.     library  = driver->root.library;
  870.     hinter   = library->auto_hinter;
  871.     autohint =
  872.       FT_BOOL( hinter                                                      &&
  873.                !( load_flags & ( FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING ) ) &&
  874.                FT_DRIVER_IS_SCALABLE( driver )                             &&
  875.                FT_DRIVER_USES_OUTLINES( driver )                           );
  876.     if ( autohint )
  877.     {
  878.       if ( FT_DRIVER_HAS_HINTER( driver ) &&
  879.            !( load_flags & FT_LOAD_FORCE_AUTOHINT ) )
  880.         autohint = 0;
  881.     }
  882.  
  883.     if ( autohint )
  884.     {
  885.       FT_AutoHinter_Interface*  hinting;
  886.  
  887.  
  888.       /* try to load embedded bitmaps first if available            */
  889.       /*                                                            */
  890.       /* XXX: This is really a temporary hack that should disappear */
  891.       /*      promptly with FreeType 2.1!                           */
  892.       /*                                                            */
  893.       if ( FT_HAS_FIXED_SIZES( face ) )
  894.       {
  895.         error = driver->clazz->load_glyph( slot, face->size,
  896.                                            glyph_index,
  897.                                            load_flags | FT_LOAD_SBITS_ONLY );
  898.  
  899.         if ( !error && slot->format == ft_glyph_format_bitmap )
  900.           goto Load_Ok;
  901.       }
  902.  
  903.       /* load auto-hinted outline */
  904.       hinting = (FT_AutoHinter_Interface*)hinter->clazz->module_interface;
  905.  
  906.       error   = hinting->load_glyph( (FT_AutoHinter)hinter,
  907.                                      slot, face->size,
  908.                                      glyph_index, load_flags );
  909.     }
  910.     else
  911.     {
  912.       error = driver->clazz->load_glyph( slot,
  913.                                          face->size,
  914.                                          glyph_index,
  915.                                          load_flags );
  916.       if ( error )
  917.         goto Exit;
  918.  
  919.       /* check that the loaded outline is correct */
  920.       error = FT_Outline_Check( &slot->outline );
  921.       if ( error )
  922.         goto Exit;
  923.     }
  924.  
  925.   Load_Ok:
  926.     /* compute the advance */
  927.     if ( load_flags & FT_LOAD_VERTICAL_LAYOUT )
  928.     {
  929.       slot->advance.x = 0;
  930.       slot->advance.y = slot->metrics.vertAdvance;
  931.     }
  932.     else
  933.     {
  934.       slot->advance.x = slot->metrics.horiAdvance;
  935.       slot->advance.y = 0;
  936.     }
  937.  
  938.     /* compute the linear advance in 16.16 pixels */
  939.     if ( ( load_flags & FT_LOAD_LINEAR_DESIGN ) == 0 )
  940.     {
  941.       FT_UInt           EM      = face->units_per_EM;
  942.       FT_Size_Metrics*  metrics = &face->size->metrics;
  943.  
  944.       slot->linearHoriAdvance = FT_MulDiv( slot->linearHoriAdvance,
  945.                                            (FT_Long)metrics->x_ppem << 16, EM );
  946.  
  947.       slot->linearVertAdvance = FT_MulDiv( slot->linearVertAdvance,
  948.                                            (FT_Long)metrics->y_ppem << 16, EM );
  949.     }
  950.  
  951.     if ( ( load_flags & FT_LOAD_IGNORE_TRANSFORM ) == 0 )
  952.     {
  953.       FT_Face_Internal  internal = face->internal;
  954.  
  955.  
  956.       /* now, transform the glyph image if needed */
  957.       if ( internal->transform_flags )
  958.       {
  959.         /* get renderer */
  960.         FT_Renderer  renderer = ft_lookup_glyph_renderer( slot );
  961.  
  962.  
  963.         if ( renderer )
  964.           error = renderer->clazz->transform_glyph(
  965.                                      renderer, slot,
  966.                                      &internal->transform_matrix,
  967.                                      &internal->transform_delta );
  968.         /* transform advance */
  969.         FT_Vector_Transform( &slot->advance, &internal->transform_matrix );
  970.       }
  971.     }
  972.  
  973.     /* do we need to render the image now? */
  974.     if ( !error                                    &&
  975.          slot->format != ft_glyph_format_bitmap    &&
  976.          slot->format != ft_glyph_format_composite &&
  977.          load_flags & FT_LOAD_RENDER )
  978.     {
  979.       error = FT_Render_Glyph( slot,
  980.                                ( load_flags & FT_LOAD_MONOCHROME )
  981.                                   ? ft_render_mode_mono
  982.                                   : ft_render_mode_normal );
  983.     }
  984.  
  985.   Exit:
  986.     return error;
  987.   }
  988.  
  989.  
  990.   /* documentation is in freetype.h */
  991.  
  992.   FT_EXPORT_DEF( FT_Error )
  993.   FT_Load_Char( FT_Face   face,
  994.                 FT_ULong  char_code,
  995.                 FT_Int    load_flags )
  996.   {
  997.     FT_UInt  glyph_index;
  998.  
  999.  
  1000.     if ( !face )
  1001.       return FT_Err_Invalid_Face_Handle;
  1002.  
  1003.     glyph_index = (FT_UInt)char_code;
  1004.     if ( face->charmap )
  1005.       glyph_index = FT_Get_Char_Index( face, char_code );
  1006.  
  1007.     return FT_Load_Glyph( face, glyph_index, load_flags );
  1008.   }
  1009.  
  1010.  
  1011.   /* destructor for sizes list */
  1012.   static void
  1013.   destroy_size( FT_Memory  memory,
  1014.                 FT_Size    size,
  1015.                 FT_Driver  driver )
  1016.   {
  1017.     /* finalize client-specific data */
  1018.     if ( size->generic.finalizer )
  1019.       size->generic.finalizer( size );
  1020.  
  1021.     /* finalize format-specific stuff */
  1022.     if ( driver->clazz->done_size )
  1023.       driver->clazz->done_size( size );
  1024.  
  1025.     FREE( size->internal );
  1026.     FREE( size );
  1027.   }
  1028.  
  1029.  
  1030.   /* destructor for faces list */
  1031.   static void
  1032.   destroy_face( FT_Memory  memory,
  1033.                 FT_Face    face,
  1034.                 FT_Driver  driver )
  1035.   {
  1036.     FT_Driver_Class*  clazz = driver->clazz;
  1037.  
  1038.  
  1039.     /* discard auto-hinting data */
  1040.     if ( face->autohint.finalizer )
  1041.       face->autohint.finalizer( face->autohint.data );
  1042.  
  1043.     /* Discard glyph slots for this face                            */
  1044.     /* Beware!  FT_Done_GlyphSlot() changes the field `face->glyph' */
  1045.     while ( face->glyph )
  1046.       FT_Done_GlyphSlot( face->glyph );
  1047.  
  1048.     /* Discard all sizes for this face */
  1049.     FT_List_Finalize( &face->sizes_list,
  1050.                      (FT_List_Destructor)destroy_size,
  1051.                      memory,
  1052.                      driver );
  1053.     face->size = 0;
  1054.  
  1055.     /* Now discard client data */
  1056.     if ( face->generic.finalizer )
  1057.       face->generic.finalizer( face );
  1058.  
  1059.     /* finalize format-specific stuff */
  1060.     if ( clazz->done_face )
  1061.       clazz->done_face( face );
  1062.  
  1063.     /* close the stream for this face if needed */
  1064.     ft_done_stream(
  1065.       &face->stream,
  1066.       ( face->face_flags & FT_FACE_FLAG_EXTERNAL_STREAM ) != 0 );
  1067.  
  1068.     /* get rid of it */
  1069.     if ( face->internal )
  1070.     {
  1071.       FREE( face->internal->postscript_name );
  1072.       FREE( face->internal );
  1073.     }
  1074.     FREE( face );
  1075.   }
  1076.  
  1077.  
  1078.   static void
  1079.   Destroy_Driver( FT_Driver  driver )
  1080.   {
  1081.     FT_List_Finalize( &driver->faces_list,
  1082.                       (FT_List_Destructor)destroy_face,
  1083.                       driver->root.memory,
  1084.                       driver );
  1085.  
  1086.     /* check whether we need to drop the driver's glyph loader */
  1087.     if ( FT_DRIVER_USES_OUTLINES( driver ) )
  1088.       FT_GlyphLoader_Done( driver->glyph_loader );
  1089.   }
  1090.  
  1091.  
  1092.   /*************************************************************************/
  1093.   /*                                                                       */
  1094.   /* <Function>                                                            */
  1095.   /*    open_face                                                          */
  1096.   /*                                                                       */
  1097.   /* <Description>                                                         */
  1098.   /*    This function does some work for FT_Open_Face().                   */
  1099.   /*                                                                       */
  1100.   static FT_Error
  1101.   open_face( FT_Driver      driver,
  1102.              FT_Stream      stream,
  1103.              FT_Long        face_index,
  1104.              FT_Int         num_params,
  1105.              FT_Parameter*  params,
  1106.              FT_Face*       aface )
  1107.   {
  1108.     FT_Memory         memory;
  1109.     FT_Driver_Class*  clazz;
  1110.     FT_Face           face = 0;
  1111.     FT_Error          error;
  1112.     FT_Face_Internal  internal;
  1113.  
  1114.  
  1115.     clazz  = driver->clazz;
  1116.     memory = driver->root.memory;
  1117.  
  1118.     /* allocate the face object and perform basic initialization */
  1119.     if ( ALLOC( face, clazz->face_object_size ) )
  1120.       goto Fail;
  1121.  
  1122.     if ( ALLOC( internal, sizeof ( *internal ) ) )
  1123.       goto Fail;
  1124.  
  1125.     face->internal = internal;
  1126.  
  1127.     face->driver   = driver;
  1128.     face->memory   = memory;
  1129.     face->stream   = stream;
  1130.  
  1131.     error = clazz->init_face( stream,
  1132.                               face,
  1133.                               face_index,
  1134.                               num_params,
  1135.                               params );
  1136.     if ( error )
  1137.       goto Fail;
  1138.  
  1139.     *aface = face;
  1140.  
  1141.   Fail:
  1142.     if ( error )
  1143.     {
  1144.       clazz->done_face( face );
  1145.       FREE( face->internal );
  1146.       FREE( face );
  1147.       *aface = 0;
  1148.     }
  1149.  
  1150.     return error;
  1151.   }
  1152.  
  1153.  
  1154.   /* there's a Mac-specific extended implementation of FT_New_Face() */
  1155.   /* in src/mac/ftmac.c                                              */
  1156.  
  1157. #ifndef macintosh
  1158.  
  1159.   /* documentation is in freetype.h */
  1160.  
  1161.   FT_EXPORT_DEF( FT_Error )
  1162.   FT_New_Face( FT_Library   library,
  1163.                const char*  pathname,
  1164.                FT_Long      face_index,
  1165.                FT_Face     *aface )
  1166.   {
  1167.     FT_Open_Args  args;
  1168.  
  1169.  
  1170.     /* test for valid `library' and `aface' delayed to FT_Open_Face() */
  1171.     if ( !pathname )
  1172.       return FT_Err_Invalid_Argument;
  1173.  
  1174.     args.flags    = ft_open_pathname;
  1175.     args.pathname = (char*)pathname;
  1176.  
  1177.     return FT_Open_Face( library, &args, face_index, aface );
  1178.   }
  1179.  
  1180. #endif  /* !macintosh */
  1181.  
  1182.  
  1183.   /* documentation is in freetype.h */
  1184.  
  1185.   FT_EXPORT_DEF( FT_Error )
  1186.   FT_New_Memory_Face( FT_Library      library,
  1187.                       const FT_Byte*  file_base,
  1188.                       FT_Long         file_size,
  1189.                       FT_Long         face_index,
  1190.                       FT_Face        *aface )
  1191.   {
  1192.     FT_Open_Args  args;
  1193.  
  1194.  
  1195.     /* test for valid `library' and `face' delayed to FT_Open_Face() */
  1196.     if ( !file_base )
  1197.       return FT_Err_Invalid_Argument;
  1198.  
  1199.     args.flags       = ft_open_memory;
  1200.     args.memory_base = file_base;
  1201.     args.memory_size = file_size;
  1202.  
  1203.     return FT_Open_Face( library, &args, face_index, aface );
  1204.   }
  1205.  
  1206.  
  1207.   /* documentation is in freetype.h */
  1208.  
  1209.   FT_EXPORT_DEF( FT_Error )
  1210.   FT_Open_Face( FT_Library     library,
  1211.                 FT_Open_Args*  args,
  1212.                 FT_Long        face_index,
  1213.                 FT_Face       *aface )
  1214.   {
  1215.     FT_Error     error;
  1216.     FT_Driver    driver;
  1217.     FT_Memory    memory;
  1218.     FT_Stream    stream;
  1219.     FT_Face      face = 0;
  1220.     FT_ListNode  node = 0;
  1221.     FT_Bool      external_stream;
  1222.  
  1223.  
  1224.     /* test for valid `library' delayed to */
  1225.     /* ft_new_input_stream()               */
  1226.  
  1227.     if ( !aface || !args )
  1228.       return FT_Err_Invalid_Argument;
  1229.  
  1230.     *aface = 0;
  1231.  
  1232.     external_stream = FT_BOOL( ( args->flags & ft_open_stream ) &&
  1233.                                args->stream                     );
  1234.  
  1235.     /* create input stream */
  1236.     error = ft_new_input_stream( library, args, &stream );
  1237.     if ( error )
  1238.       goto Exit;
  1239.  
  1240.     memory = library->memory;
  1241.  
  1242.     /* If the font driver is specified in the `args' structure, use */
  1243.     /* it.  Otherwise, we scan the list of registered drivers.      */
  1244.     if ( ( args->flags & ft_open_driver ) && args->driver )
  1245.     {
  1246.       driver = FT_DRIVER( args->driver );
  1247.  
  1248.       /* not all modules are drivers, so check... */
  1249.       if ( FT_MODULE_IS_DRIVER( driver ) )
  1250.       {
  1251.         FT_Int         num_params = 0;
  1252.         FT_Parameter*  params     = 0;
  1253.  
  1254.  
  1255.         if ( args->flags & ft_open_params )
  1256.         {
  1257.           num_params = args->num_params;
  1258.           params     = args->params;
  1259.         }
  1260.  
  1261.         error = open_face( driver, stream, face_index,
  1262.                            num_params, params, &face );
  1263.         if ( !error )
  1264.           goto Success;
  1265.       }
  1266.       else
  1267.         error = FT_Err_Invalid_Handle;
  1268.  
  1269.       ft_done_stream( &stream, external_stream );
  1270.       goto Fail;
  1271.     }
  1272.     else
  1273.     {
  1274.       /* check each font driver for an appropriate format */
  1275.       FT_Module*  cur   = library->modules;
  1276.       FT_Module*  limit = cur + library->num_modules;
  1277.  
  1278.  
  1279.       for ( ; cur < limit; cur++ )
  1280.       {
  1281.         /* not all modules are font drivers, so check... */
  1282.         if ( FT_MODULE_IS_DRIVER( cur[0] ) )
  1283.         {
  1284.           FT_Int         num_params = 0;
  1285.           FT_Parameter*  params     = 0;
  1286.  
  1287.  
  1288.           driver = FT_DRIVER( cur[0] );
  1289.  
  1290.           if ( args->flags & ft_open_params )
  1291.           {
  1292.             num_params = args->num_params;
  1293.             params     = args->params;
  1294.           }
  1295.  
  1296.           error = open_face( driver, stream, face_index,
  1297.                              num_params, params, &face );
  1298.           if ( !error )
  1299.             goto Success;
  1300.  
  1301.           if ( FT_ERROR_BASE( error ) != FT_Err_Unknown_File_Format )
  1302.             goto Fail2;
  1303.         }
  1304.       }
  1305.  
  1306.       /* no driver is able to handle this format */
  1307.       error = FT_Err_Unknown_File_Format;
  1308.  
  1309.   Fail2:
  1310.       ft_done_stream( &stream, external_stream );
  1311.       goto Fail;
  1312.     }
  1313.  
  1314.   Success:
  1315.     FT_TRACE4(( "FT_Open_Face: New face object, adding to list\n" ));
  1316.  
  1317.     /* set the FT_FACE_FLAG_EXTERNAL_STREAM bit for FT_Done_Face */
  1318.     if ( external_stream )
  1319.       face->face_flags |= FT_FACE_FLAG_EXTERNAL_STREAM;
  1320.  
  1321.     /* add the face object to its driver's list */
  1322.     if ( ALLOC( node, sizeof ( *node ) ) )
  1323.       goto Fail;
  1324.  
  1325.     node->data = face;
  1326.     /* don't assume driver is the same as face->driver, so use */
  1327.     /* face->driver instead.                                   */
  1328.     FT_List_Add( &face->driver->faces_list, node );
  1329.  
  1330.     /* now allocate a glyph slot object for the face */
  1331.     {
  1332.       FT_GlyphSlot  slot;
  1333.  
  1334.  
  1335.       FT_TRACE4(( "FT_Open_Face: Creating glyph slot\n" ));
  1336.  
  1337.       error = FT_New_GlyphSlot( face, &slot );
  1338.       if ( error )
  1339.         goto Fail;
  1340.  
  1341.       face->glyph = slot;
  1342.     }
  1343.  
  1344.     /* finally, allocate a size object for the face */
  1345.     {
  1346.       FT_Size  size;
  1347.  
  1348.  
  1349.       FT_TRACE4(( "FT_Open_Face: Creating size object\n" ));
  1350.  
  1351.       error = FT_New_Size( face, &size );
  1352.       if ( error )
  1353.         goto Fail;
  1354.  
  1355.       face->size = size;
  1356.     }
  1357.  
  1358.     /* initialize internal face data */
  1359.     {
  1360.       FT_Face_Internal  internal = face->internal;
  1361.  
  1362.  
  1363.       internal->transform_matrix.xx = 0x10000L;
  1364.       internal->transform_matrix.xy = 0;
  1365.       internal->transform_matrix.yx = 0;
  1366.       internal->transform_matrix.yy = 0x10000L;
  1367.  
  1368.       internal->transform_delta.x = 0;
  1369.       internal->transform_delta.y = 0;
  1370.     }
  1371.  
  1372.     *aface = face;
  1373.     goto Exit;
  1374.  
  1375.   Fail:
  1376.     FT_Done_Face( face );
  1377.  
  1378.   Exit:
  1379.     FT_TRACE4(( "FT_Open_Face: Return %d\n", error ));
  1380.  
  1381.     return error;
  1382.   }
  1383.  
  1384.  
  1385.   /* documentation is in freetype.h */
  1386.  
  1387.   FT_EXPORT_DEF( FT_Error )
  1388.   FT_Attach_File( FT_Face      face,
  1389.                   const char*  filepathname )
  1390.   {
  1391.     FT_Open_Args  open;
  1392.  
  1393.  
  1394.     /* test for valid `face' delayed to FT_Attach_Stream() */
  1395.  
  1396.     if ( !filepathname )
  1397.       return FT_Err_Invalid_Argument;
  1398.  
  1399.     open.flags    = ft_open_pathname;
  1400.     open.pathname = (char*)filepathname;
  1401.  
  1402.     return FT_Attach_Stream( face, &open );
  1403.   }
  1404.  
  1405.  
  1406.   /* documentation is in freetype.h */
  1407.  
  1408.   FT_EXPORT_DEF( FT_Error )
  1409.   FT_Attach_Stream( FT_Face        face,
  1410.                     FT_Open_Args*  parameters )
  1411.   {
  1412.     FT_Stream  stream;
  1413.     FT_Error   error;
  1414.     FT_Driver  driver;
  1415.  
  1416.     FT_Driver_Class*  clazz;
  1417.  
  1418.  
  1419.     /* test for valid `parameters' delayed to ft_new_input_stream() */
  1420.  
  1421.     if ( !face )
  1422.       return FT_Err_Invalid_Face_Handle;
  1423.  
  1424.     driver = face->driver;
  1425.     if ( !driver )
  1426.       return FT_Err_Invalid_Driver_Handle;
  1427.  
  1428.     error = ft_new_input_stream( driver->root.library, parameters, &stream );
  1429.     if ( error )
  1430.       goto Exit;
  1431.  
  1432.     /* we implement FT_Attach_Stream in each driver through the */
  1433.     /* `attach_file' interface                                  */
  1434.  
  1435.     error = FT_Err_Unimplemented_Feature;
  1436.     clazz = driver->clazz;
  1437.     if ( clazz->attach_file )
  1438.       error = clazz->attach_file( face, stream );
  1439.  
  1440.     /* close the attached stream */
  1441.     ft_done_stream( &stream,
  1442.                     (FT_Bool)( parameters->stream &&
  1443.                                ( parameters->flags & ft_open_stream ) ) );
  1444.  
  1445.   Exit:
  1446.     return error;
  1447.   }
  1448.  
  1449.  
  1450.   /* documentation is in freetype.h */
  1451.  
  1452.   FT_EXPORT_DEF( FT_Error )
  1453.   FT_Done_Face( FT_Face  face )
  1454.   {
  1455.     FT_Error     error;
  1456.     FT_Driver    driver;
  1457.     FT_Memory    memory;
  1458.     FT_ListNode  node;
  1459.  
  1460.  
  1461.     error = FT_Err_Invalid_Face_Handle;
  1462.     if ( face && face->driver )
  1463.     {
  1464.       driver = face->driver;
  1465.       memory = driver->root.memory;
  1466.  
  1467.       /* find face in driver's list */
  1468.       node = FT_List_Find( &driver->faces_list, face );
  1469.       if ( node )
  1470.       {
  1471.         /* remove face object from the driver's list */
  1472.         FT_List_Remove( &driver->faces_list, node );
  1473.         FREE( node );
  1474.  
  1475.         /* now destroy the object proper */
  1476.         destroy_face( memory, face, driver );
  1477.         error = FT_Err_Ok;
  1478.       }
  1479.     }
  1480.     return error;
  1481.   }
  1482.  
  1483.  
  1484.   /* documentation is in ftobjs.h */
  1485.  
  1486.   FT_EXPORT_DEF( FT_Error )
  1487.   FT_New_Size( FT_Face   face,
  1488.                FT_Size  *asize )
  1489.   {
  1490.     FT_Error          error;
  1491.     FT_Memory         memory;
  1492.     FT_Driver         driver;
  1493.     FT_Driver_Class*  clazz;
  1494.  
  1495.     FT_Size           size = 0;
  1496.     FT_ListNode       node = 0;
  1497.  
  1498.  
  1499.     if ( !face )
  1500.       return FT_Err_Invalid_Face_Handle;
  1501.  
  1502.     if ( !asize )
  1503.       return FT_Err_Invalid_Size_Handle;
  1504.  
  1505.     if ( !face->driver )
  1506.       return FT_Err_Invalid_Driver_Handle;
  1507.  
  1508.     *asize = 0;
  1509.  
  1510.     driver = face->driver;
  1511.     clazz  = driver->clazz;
  1512.     memory = face->memory;
  1513.  
  1514.     /* Allocate new size object and perform basic initialisation */
  1515.     if ( ALLOC( size, clazz->size_object_size ) ||
  1516.          ALLOC( node, sizeof ( FT_ListNodeRec ) ) )
  1517.       goto Exit;
  1518.  
  1519.     size->face = face;
  1520.  
  1521.     /* for now, do not use any internal fields in size objects */
  1522.     size->internal = 0;
  1523.  
  1524.     if ( clazz->init_size )
  1525.       error = clazz->init_size( size );
  1526.  
  1527.     /* in case of success, add to the face's list */
  1528.     if ( !error )
  1529.     {
  1530.       *asize     = size;
  1531.       node->data = size;
  1532.       FT_List_Add( &face->sizes_list, node );
  1533.     }
  1534.  
  1535.   Exit:
  1536.     if ( error )
  1537.     {
  1538.       FREE( node );
  1539.       FREE( size );
  1540.     }
  1541.  
  1542.     return error;
  1543.   }
  1544.  
  1545.  
  1546.   /* documentation is in ftobjs.h */
  1547.  
  1548.   FT_EXPORT_DEF( FT_Error )
  1549.   FT_Done_Size( FT_Size  size )
  1550.   {
  1551.     FT_Error     error;
  1552.     FT_Driver    driver;
  1553.     FT_Memory    memory;
  1554.     FT_Face      face;
  1555.     FT_ListNode  node;
  1556.  
  1557.  
  1558.     if ( !size )
  1559.       return FT_Err_Invalid_Size_Handle;
  1560.  
  1561.     face = size->face;
  1562.     if ( !face )
  1563.       return FT_Err_Invalid_Face_Handle;
  1564.  
  1565.     driver = face->driver;
  1566.     if ( !driver )
  1567.       return FT_Err_Invalid_Driver_Handle;
  1568.  
  1569.     memory = driver->root.memory;
  1570.  
  1571.     error = FT_Err_Ok;
  1572.     node  = FT_List_Find( &face->sizes_list, size );
  1573.     if ( node )
  1574.     {
  1575.       FT_List_Remove( &face->sizes_list, node );
  1576.       FREE( node );
  1577.  
  1578.       if ( face->size == size )
  1579.       {
  1580.         face->size = 0;
  1581.         if ( face->sizes_list.head )
  1582.           face->size = (FT_Size)(face->sizes_list.head->data);
  1583.       }
  1584.  
  1585.       destroy_size( memory, size, driver );
  1586.     }
  1587.     else
  1588.       error = FT_Err_Invalid_Size_Handle;
  1589.  
  1590.     return error;
  1591.   }
  1592.  
  1593.  
  1594.   static void
  1595.   ft_recompute_scaled_metrics( FT_Face           face,
  1596.                                FT_Size_Metrics*  metrics )
  1597.   {
  1598.     /* Compute root ascender, descender, test height, and max_advance */
  1599.  
  1600.     metrics->ascender    = ( FT_MulFix( face->ascender,
  1601.                                         metrics->y_scale ) + 32 ) & -64;
  1602.  
  1603.     metrics->descender   = ( FT_MulFix( face->descender,
  1604.                                         metrics->y_scale ) + 32 ) & -64;
  1605.  
  1606.     metrics->height      = ( FT_MulFix( face->height,
  1607.                                         metrics->y_scale ) + 32 ) & -64;
  1608.  
  1609.     metrics->max_advance = ( FT_MulFix( face->max_advance_width,
  1610.                                         metrics->x_scale ) + 32 ) & -64;
  1611.   }
  1612.  
  1613.  
  1614.   /* documentation is in freetype.h */
  1615.  
  1616.   FT_EXPORT_DEF( FT_Error )
  1617.   FT_Set_Char_Size( FT_Face     face,
  1618.                     FT_F26Dot6  char_width,
  1619.                     FT_F26Dot6  char_height,
  1620.                     FT_UInt     horz_resolution,
  1621.                     FT_UInt     vert_resolution )
  1622.   {
  1623.     FT_Error          error = FT_Err_Ok;
  1624.     FT_Driver         driver;
  1625.     FT_Driver_Class*  clazz;
  1626.     FT_Size_Metrics*  metrics;
  1627.     FT_Long           dim_x, dim_y;
  1628.  
  1629.  
  1630.     if ( !face || !face->size || !face->driver )
  1631.       return FT_Err_Invalid_Face_Handle;
  1632.  
  1633.     driver  = face->driver;
  1634.     metrics = &face->size->metrics;
  1635.  
  1636.     if ( !char_width )
  1637.       char_width = char_height;
  1638.  
  1639.     else if ( !char_height )
  1640.       char_height = char_width;
  1641.  
  1642.     if ( !horz_resolution )
  1643.       horz_resolution = 72;
  1644.  
  1645.     if ( !vert_resolution )
  1646.       vert_resolution = 72;
  1647.  
  1648.     driver = face->driver;
  1649.     clazz  = driver->clazz;
  1650.  
  1651.     /* default processing -- this can be overridden by the driver */
  1652.     if ( char_width  < 1 * 64 )
  1653.       char_width  = 1 * 64;
  1654.     if ( char_height < 1 * 64 )
  1655.       char_height = 1 * 64;
  1656.  
  1657.     /* Compute pixel sizes in 26.6 units */
  1658.     dim_x = ( ( ( char_width  * horz_resolution ) / 72 ) + 32 ) & -64;
  1659.     dim_y = ( ( ( char_height * vert_resolution ) / 72 ) + 32 ) & -64;
  1660.  
  1661.     metrics->x_ppem  = (FT_UShort)( dim_x >> 6 );
  1662.     metrics->y_ppem  = (FT_UShort)( dim_y >> 6 );
  1663.  
  1664.     metrics->x_scale = 0x10000L;
  1665.     metrics->y_scale = 0x10000L;
  1666.  
  1667.     if ( face->face_flags & FT_FACE_FLAG_SCALABLE )
  1668.     {
  1669.       metrics->x_scale = FT_DivFix( dim_x, face->units_per_EM );
  1670.       metrics->y_scale = FT_DivFix( dim_y, face->units_per_EM );
  1671.  
  1672.       ft_recompute_scaled_metrics( face, metrics );
  1673.     }
  1674.  
  1675.     if ( clazz->set_char_sizes )
  1676.       error = clazz->set_char_sizes( face->size,
  1677.                                      char_width,
  1678.                                      char_height,
  1679.                                      horz_resolution,
  1680.                                      vert_resolution );
  1681.     return error;
  1682.   }
  1683.  
  1684.  
  1685.   /* documentation is in freetype.h */
  1686.  
  1687.   FT_EXPORT_DEF( FT_Error )
  1688.   FT_Set_Pixel_Sizes( FT_Face  face,
  1689.                       FT_UInt  pixel_width,
  1690.                       FT_UInt  pixel_height )
  1691.   {
  1692.     FT_Error          error = FT_Err_Ok;
  1693.     FT_Driver         driver;
  1694.     FT_Driver_Class*  clazz;
  1695.     FT_Size_Metrics*  metrics = &face->size->metrics;
  1696.  
  1697.  
  1698.     if ( !face || !face->size || !face->driver )
  1699.       return FT_Err_Invalid_Face_Handle;
  1700.  
  1701.     driver = face->driver;
  1702.     clazz  = driver->clazz;
  1703.  
  1704.     /* default processing -- this can be overridden by the driver */
  1705.     if ( pixel_width == 0 )
  1706.       pixel_width = pixel_height;
  1707.  
  1708.     else if ( pixel_height == 0 )
  1709.       pixel_height = pixel_width;
  1710.  
  1711.     if ( pixel_width  < 1 )
  1712.       pixel_width  = 1;
  1713.     if ( pixel_height < 1 )
  1714.       pixel_height = 1;
  1715.  
  1716.     metrics->x_ppem = (FT_UShort)pixel_width;
  1717.     metrics->y_ppem = (FT_UShort)pixel_height;
  1718.  
  1719.     if ( face->face_flags & FT_FACE_FLAG_SCALABLE )
  1720.     {
  1721.       metrics->x_scale = FT_DivFix( metrics->x_ppem << 6,
  1722.                                     face->units_per_EM );
  1723.  
  1724.       metrics->y_scale = FT_DivFix( metrics->y_ppem << 6,
  1725.                                     face->units_per_EM );
  1726.  
  1727.       ft_recompute_scaled_metrics( face, metrics );
  1728.     }
  1729.  
  1730.     if ( clazz->set_pixel_sizes )
  1731.       error = clazz->set_pixel_sizes( face->size,
  1732.                                       pixel_width,
  1733.                                       pixel_height );
  1734.     return error;
  1735.   }
  1736.  
  1737.  
  1738.   /* documentation is in freetype.h */
  1739.  
  1740.   FT_EXPORT_DEF( FT_Error )
  1741.   FT_Get_Kerning( FT_Face     face,
  1742.                   FT_UInt     left_glyph,
  1743.                   FT_UInt     right_glyph,
  1744.                   FT_UInt     kern_mode,
  1745.                   FT_Vector  *akerning )
  1746.   {
  1747.     FT_Error   error = FT_Err_Ok;
  1748.     FT_Driver  driver;
  1749.  
  1750.  
  1751.     if ( !face )
  1752.       return FT_Err_Invalid_Face_Handle;
  1753.  
  1754.     if ( !akerning )
  1755.       return FT_Err_Invalid_Argument;
  1756.  
  1757.     driver = face->driver;
  1758.  
  1759.     akerning->x = 0;
  1760.     akerning->y = 0;
  1761.  
  1762.     if ( driver->clazz->get_kerning )
  1763.     {
  1764.       error = driver->clazz->get_kerning( face,
  1765.                                           left_glyph,
  1766.                                           right_glyph,
  1767.                                           akerning );
  1768.       if ( !error )
  1769.       {
  1770.         if ( kern_mode != ft_kerning_unscaled )
  1771.         {
  1772.           akerning->x = FT_MulFix( akerning->x, face->size->metrics.x_scale );
  1773.           akerning->y = FT_MulFix( akerning->y, face->size->metrics.y_scale );
  1774.  
  1775.           if ( kern_mode != ft_kerning_unfitted )
  1776.           {
  1777.             akerning->x = ( akerning->x + 32 ) & -64;
  1778.             akerning->y = ( akerning->y + 32 ) & -64;
  1779.           }
  1780.         }
  1781.       }
  1782.     }
  1783.  
  1784.     return error;
  1785.   }
  1786.  
  1787.  
  1788.   /* documentation is in freetype.h */
  1789.  
  1790.   FT_EXPORT_DEF( FT_Error )
  1791.   FT_Select_Charmap( FT_Face      face,
  1792.                      FT_Encoding  encoding )
  1793.   {
  1794.     FT_CharMap*  cur;
  1795.     FT_CharMap*  limit;
  1796.  
  1797.  
  1798.     if ( !face )
  1799.       return FT_Err_Invalid_Face_Handle;
  1800.  
  1801.     cur = face->charmaps;
  1802.     if ( !cur )
  1803.       return FT_Err_Invalid_CharMap_Handle;
  1804.  
  1805.     limit = cur + face->num_charmaps;
  1806.  
  1807.     for ( ; cur < limit; cur++ )
  1808.     {
  1809.       if ( cur[0]->encoding == encoding )
  1810.       {
  1811.         face->charmap = cur[0];
  1812.         return 0;
  1813.       }
  1814.     }
  1815.  
  1816.     return FT_Err_Invalid_Argument;
  1817.   }
  1818.  
  1819.  
  1820.   /* documentation is in freetype.h */
  1821.  
  1822.   FT_EXPORT_DEF( FT_Error )
  1823.   FT_Set_Charmap( FT_Face     face,
  1824.                   FT_CharMap  charmap )
  1825.   {
  1826.     FT_CharMap*  cur;
  1827.     FT_CharMap*  limit;
  1828.  
  1829.  
  1830.     if ( !face )
  1831.       return FT_Err_Invalid_Face_Handle;
  1832.  
  1833.     cur = face->charmaps;
  1834.     if ( !cur )
  1835.       return FT_Err_Invalid_CharMap_Handle;
  1836.  
  1837.     limit = cur + face->num_charmaps;
  1838.  
  1839.     for ( ; cur < limit; cur++ )
  1840.     {
  1841.       if ( cur[0] == charmap )
  1842.       {
  1843.         face->charmap = cur[0];
  1844.         return 0;
  1845.       }
  1846.     }
  1847.     return FT_Err_Invalid_Argument;
  1848.   }
  1849.  
  1850.  
  1851.   /* documentation is in freetype.h */
  1852.  
  1853.   FT_EXPORT_DEF( FT_UInt )
  1854.   FT_Get_Char_Index( FT_Face   face,
  1855.                      FT_ULong  charcode )
  1856.   {
  1857.     FT_UInt    result;
  1858.     FT_Driver  driver;
  1859.  
  1860.  
  1861.     result = 0;
  1862.     if ( face && face->charmap )
  1863.     {
  1864.       driver = face->driver;
  1865.       result = driver->clazz->get_char_index( face->charmap, charcode );
  1866.     }
  1867.     return result;
  1868.   }
  1869.  
  1870.  
  1871.   /* documentation is in freetype.h */
  1872.  
  1873.   FT_EXPORT_DEF( FT_ULong )
  1874.   FT_Get_First_Char( FT_Face   face,
  1875.                      FT_UInt  *agindex )
  1876.   {
  1877.     FT_ULong   result = 0;
  1878.     FT_UInt    gindex = 0;
  1879.     
  1880.     if ( face && face->charmap )
  1881.     {
  1882.       gindex = FT_Get_Char_Index( face, 0 );
  1883.       if ( gindex == 0 )
  1884.         result = FT_Get_Next_Char( face, 0, &gindex );
  1885.     }
  1886.     
  1887.     if ( agindex  )
  1888.       *agindex = gindex;
  1889.       
  1890.     return result;
  1891.   }
  1892.  
  1893.   /* documentation is in freetype.h */
  1894.  
  1895.   FT_EXPORT_DEF( FT_ULong )
  1896.   FT_Get_Next_Char( FT_Face   face,
  1897.                     FT_ULong  charcode,
  1898.                     FT_UInt  *agindex )
  1899.   {
  1900.     FT_ULong   result = 0;
  1901.     FT_UInt    gindex = 0;
  1902.     FT_Driver  driver;
  1903.  
  1904.  
  1905.     if ( face && face->charmap )
  1906.     {
  1907.       driver = face->driver;
  1908.       result = driver->clazz->get_next_char( face->charmap, charcode );
  1909.       if ( result != 0 )
  1910.       {
  1911.         gindex = driver->clazz->get_char_index( face->charmap, result );
  1912.         if ( gindex == 0 )
  1913.           result = 0;
  1914.       }
  1915.     }
  1916.     
  1917.     if ( agindex )
  1918.       *agindex = gindex;
  1919.       
  1920.     return result;
  1921.   }
  1922.  
  1923.  
  1924.   /* documentation is in freetype.h */
  1925.  
  1926.   FT_EXPORT_DEF( FT_UInt )
  1927.   FT_Get_Name_Index( FT_Face     face,
  1928.                      FT_String*  glyph_name )
  1929.   {
  1930.     FT_UInt  result = 0;
  1931.  
  1932.  
  1933.     if ( face && FT_HAS_GLYPH_NAMES( face ) )
  1934.     {
  1935.       /* now, lookup for glyph name */
  1936.       FT_Driver         driver = face->driver;
  1937.       FT_Module_Class*  clazz  = FT_MODULE_CLASS( driver );
  1938.  
  1939.  
  1940.       if ( clazz->get_interface )
  1941.       {
  1942.         FT_Name_Index_Requester  requester;
  1943.  
  1944.  
  1945.         requester = (FT_Name_Index_Requester)clazz->get_interface(
  1946.                       FT_MODULE( driver ), "name_index" );
  1947.         if ( requester )
  1948.           result = requester( face, glyph_name );
  1949.       }
  1950.     }
  1951.  
  1952.     return result;
  1953.   }
  1954.  
  1955.  
  1956.   /* documentation is in freetype.h */
  1957.  
  1958.   FT_EXPORT_DEF( FT_Error )
  1959.   FT_Get_Glyph_Name( FT_Face     face,
  1960.                      FT_UInt     glyph_index,
  1961.                      FT_Pointer  buffer,
  1962.                      FT_UInt     buffer_max )
  1963.   {
  1964.     FT_Error  error = FT_Err_Invalid_Argument;
  1965.  
  1966.  
  1967.     /* clean up buffer */
  1968.     if ( buffer && buffer_max > 0 )
  1969.       ((FT_Byte*)buffer)[0] = 0;
  1970.  
  1971.     if ( face                                    &&
  1972.          glyph_index < (FT_UInt)face->num_glyphs &&
  1973.          FT_HAS_GLYPH_NAMES( face )              )
  1974.     {
  1975.       /* now, lookup for glyph name */
  1976.       FT_Driver        driver = face->driver;
  1977.       FT_Module_Class* clazz  = FT_MODULE_CLASS( driver );
  1978.  
  1979.  
  1980.       if ( clazz->get_interface )
  1981.       {
  1982.         FT_Glyph_Name_Requester  requester;
  1983.  
  1984.  
  1985.         requester = (FT_Glyph_Name_Requester)clazz->get_interface(
  1986.                       FT_MODULE( driver ), "glyph_name" );
  1987.         if ( requester )
  1988.           error = requester( face, glyph_index, buffer, buffer_max );
  1989.       }
  1990.     }
  1991.  
  1992.     return error;
  1993.   }
  1994.  
  1995.  
  1996.   /* documentation is in freetype.h */
  1997.  
  1998.   FT_EXPORT_DEF( const char* )
  1999.   FT_Get_Postscript_Name( FT_Face  face )
  2000.   {
  2001.     const char*  result = NULL;
  2002.  
  2003.  
  2004.     if ( !face )
  2005.       goto Exit;
  2006.  
  2007.     result = face->internal->postscript_name;
  2008.     if ( !result )
  2009.     {
  2010.       /* now, lookup for glyph name */
  2011.       FT_Driver         driver = face->driver;
  2012.       FT_Module_Class*  clazz  = FT_MODULE_CLASS( driver );
  2013.  
  2014.  
  2015.       if ( clazz->get_interface )
  2016.       {
  2017.         FT_PSName_Requester  requester;
  2018.  
  2019.  
  2020.         requester = (FT_PSName_Requester)clazz->get_interface(
  2021.                       FT_MODULE( driver ), "postscript_name" );
  2022.         if ( requester )
  2023.           result = requester( face );
  2024.       }
  2025.     }
  2026.   Exit:
  2027.     return result;
  2028.   }
  2029.  
  2030.  
  2031.   /* documentation is in tttables.h */
  2032.  
  2033.   FT_EXPORT_DEF( void* )
  2034.   FT_Get_Sfnt_Table( FT_Face      face,
  2035.                      FT_Sfnt_Tag  tag )
  2036.   {
  2037.     void*                   table = 0;
  2038.     FT_Get_Sfnt_Table_Func  func;
  2039.     FT_Driver               driver;
  2040.  
  2041.  
  2042.     if ( !face || !FT_IS_SFNT( face ) )
  2043.       goto Exit;
  2044.  
  2045.     driver = face->driver;
  2046.     func = (FT_Get_Sfnt_Table_Func)driver->root.clazz->get_interface(
  2047.                                      FT_MODULE( driver ), "get_sfnt" );
  2048.     if ( func )
  2049.       table = func( face, tag );
  2050.  
  2051.   Exit:
  2052.     return table;
  2053.   }
  2054.  
  2055.  
  2056.   FT_EXPORT_DEF( FT_Error )
  2057.   FT_Activate_Size( FT_Size  size )
  2058.   {
  2059.     FT_Face  face;
  2060.  
  2061.  
  2062.     if ( size == NULL )
  2063.       return FT_Err_Bad_Argument;
  2064.  
  2065.     face = size->face;
  2066.     if ( face == NULL || face->driver == NULL )
  2067.       return FT_Err_Bad_Argument;
  2068.  
  2069.     /* we don't need anything more complex than that; all size objects */
  2070.     /* are already listed by the face                                  */
  2071.     face->size = size;
  2072.  
  2073.     return FT_Err_Ok;
  2074.   }
  2075.  
  2076.  
  2077.   /*************************************************************************/
  2078.   /*************************************************************************/
  2079.   /*************************************************************************/
  2080.   /****                                                                 ****/
  2081.   /****                                                                 ****/
  2082.   /****                        R E N D E R E R S                        ****/
  2083.   /****                                                                 ****/
  2084.   /****                                                                 ****/
  2085.   /*************************************************************************/
  2086.   /*************************************************************************/
  2087.   /*************************************************************************/
  2088.  
  2089.   /* lookup a renderer by glyph format in the library's list */
  2090.   FT_BASE_DEF( FT_Renderer )
  2091.   FT_Lookup_Renderer( FT_Library       library,
  2092.                       FT_Glyph_Format  format,
  2093.                       FT_ListNode*     node )
  2094.   {
  2095.     FT_ListNode   cur;
  2096.     FT_Renderer   result = 0;
  2097.  
  2098.  
  2099.     if ( !library )
  2100.       goto Exit;
  2101.  
  2102.     cur = library->renderers.head;
  2103.  
  2104.     if ( node )
  2105.     {
  2106.       if ( *node )
  2107.         cur = (*node)->next;
  2108.       *node = 0;
  2109.     }
  2110.  
  2111.     while ( cur )
  2112.     {
  2113.       FT_Renderer  renderer = FT_RENDERER( cur->data );
  2114.  
  2115.  
  2116.       if ( renderer->glyph_format == format )
  2117.       {
  2118.         if ( node )
  2119.           *node = cur;
  2120.  
  2121.         result = renderer;
  2122.         break;
  2123.       }
  2124.       cur = cur->next;
  2125.     }
  2126.  
  2127.   Exit:
  2128.     return result;
  2129.   }
  2130.  
  2131.  
  2132.   static FT_Renderer
  2133.   ft_lookup_glyph_renderer( FT_GlyphSlot  slot )
  2134.   {
  2135.     FT_Face      face    = slot->face;
  2136.     FT_Library   library = FT_FACE_LIBRARY( face );
  2137.     FT_Renderer  result  = library->cur_renderer;
  2138.  
  2139.  
  2140.     if ( !result || result->glyph_format != slot->format )
  2141.       result = FT_Lookup_Renderer( library, slot->format, 0 );
  2142.  
  2143.     return result;
  2144.   }
  2145.  
  2146.  
  2147.   static void
  2148.   ft_set_current_renderer( FT_Library  library )
  2149.   {
  2150.     FT_Renderer  renderer;
  2151.  
  2152.  
  2153.     renderer = FT_Lookup_Renderer( library, ft_glyph_format_outline, 0 );
  2154.     library->cur_renderer = renderer;
  2155.   }
  2156.  
  2157.  
  2158.   static FT_Error
  2159.   ft_add_renderer( FT_Module  module )
  2160.   {
  2161.     FT_Library   library = module->library;
  2162.     FT_Memory    memory  = library->memory;
  2163.     FT_Error     error;
  2164.     FT_ListNode  node;
  2165.  
  2166.  
  2167.     if ( ALLOC( node, sizeof ( *node ) ) )
  2168.       goto Exit;
  2169.  
  2170.     {
  2171.       FT_Renderer         render = FT_RENDERER( module );
  2172.       FT_Renderer_Class*  clazz  = (FT_Renderer_Class*)module->clazz;
  2173.  
  2174.  
  2175.       render->clazz        = clazz;
  2176.       render->glyph_format = clazz->glyph_format;
  2177.  
  2178.       /* allocate raster object if needed */
  2179.       if ( clazz->glyph_format == ft_glyph_format_outline &&
  2180.            clazz->raster_class->raster_new )
  2181.       {
  2182.         error = clazz->raster_class->raster_new( memory, &render->raster );
  2183.         if ( error )
  2184.           goto Fail;
  2185.  
  2186.         render->raster_render = clazz->raster_class->raster_render;
  2187.         render->render        = clazz->render_glyph;
  2188.       }
  2189.  
  2190.       /* add to list */
  2191.       node->data = module;
  2192.       FT_List_Add( &library->renderers, node );
  2193.  
  2194.       ft_set_current_renderer( library );
  2195.     }
  2196.  
  2197.   Fail:
  2198.     if ( error )
  2199.       FREE( node );
  2200.  
  2201.   Exit:
  2202.     return error;
  2203.   }
  2204.  
  2205.  
  2206.   static void
  2207.   ft_remove_renderer( FT_Module  module )
  2208.   {
  2209.     FT_Library   library = module->library;
  2210.     FT_Memory    memory  = library->memory;
  2211.     FT_ListNode  node;
  2212.  
  2213.  
  2214.     node = FT_List_Find( &library->renderers, module );
  2215.     if ( node )
  2216.     {
  2217.       FT_Renderer  render = FT_RENDERER( module );
  2218.  
  2219.  
  2220.       /* release raster object, if any */
  2221.       if ( render->raster )
  2222.         render->clazz->raster_class->raster_done( render->raster );
  2223.  
  2224.       /* remove from list */
  2225.       FT_List_Remove( &library->renderers, node );
  2226.       FREE( node );
  2227.  
  2228.       ft_set_current_renderer( library );
  2229.     }
  2230.   }
  2231.  
  2232.  
  2233.   /* documentation is in ftrender.h */
  2234.  
  2235.   FT_EXPORT_DEF( FT_Renderer )
  2236.   FT_Get_Renderer( FT_Library       library,
  2237.                    FT_Glyph_Format  format )
  2238.   {
  2239.     /* test for valid `library' delayed to FT_Lookup_Renderer() */
  2240.  
  2241.     return  FT_Lookup_Renderer( library, format, 0 );
  2242.   }
  2243.  
  2244.  
  2245.   /* documentation is in ftrender.h */
  2246.  
  2247.   FT_EXPORT_DEF( FT_Error )
  2248.   FT_Set_Renderer( FT_Library     library,
  2249.                    FT_Renderer    renderer,
  2250.                    FT_UInt        num_params,
  2251.                    FT_Parameter*  parameters )
  2252.   {
  2253.     FT_ListNode  node;
  2254.     FT_Error     error = FT_Err_Ok;
  2255.  
  2256.  
  2257.     if ( !library )
  2258.       return FT_Err_Invalid_Library_Handle;
  2259.  
  2260.     if ( !renderer )
  2261.       return FT_Err_Invalid_Argument;
  2262.  
  2263.     node = FT_List_Find( &library->renderers, renderer );
  2264.     if ( !node )
  2265.     {
  2266.       error = FT_Err_Invalid_Argument;
  2267.       goto Exit;
  2268.     }
  2269.  
  2270.     FT_List_Up( &library->renderers, node );
  2271.  
  2272.     if ( renderer->glyph_format == ft_glyph_format_outline )
  2273.       library->cur_renderer = renderer;
  2274.  
  2275.     if ( num_params > 0 )
  2276.     {
  2277.       FTRenderer_setMode  set_mode = renderer->clazz->set_mode;
  2278.  
  2279.  
  2280.       for ( ; num_params > 0; num_params-- )
  2281.       {
  2282.         error = set_mode( renderer, parameters->tag, parameters->data );
  2283.         if ( error )
  2284.           break;
  2285.       }
  2286.     }
  2287.  
  2288.   Exit:
  2289.     return error;
  2290.   }
  2291.  
  2292.  
  2293.   FT_EXPORT_DEF( FT_Error )
  2294.   FT_Render_Glyph_Internal( FT_Library    library,
  2295.                             FT_GlyphSlot  slot,
  2296.                             FT_UInt       render_mode )
  2297.   {
  2298.     FT_Error     error = FT_Err_Ok;
  2299.     FT_Renderer  renderer;
  2300.  
  2301.  
  2302.     /* if it is already a bitmap, no need to do anything */
  2303.     switch ( slot->format )
  2304.     {
  2305.     case ft_glyph_format_bitmap:   /* already a bitmap, don't do anything */
  2306.       break;
  2307.  
  2308.     default:
  2309.       {
  2310.         FT_ListNode  node   = 0;
  2311.         FT_Bool      update = 0;
  2312.  
  2313.  
  2314.         /* small shortcut for the very common case */
  2315.         if ( slot->format == ft_glyph_format_outline )
  2316.         {
  2317.           renderer = library->cur_renderer;
  2318.           node     = library->renderers.head;
  2319.         }
  2320.         else
  2321.           renderer = FT_Lookup_Renderer( library, slot->format, &node );
  2322.  
  2323.         error = FT_Err_Unimplemented_Feature;
  2324.         while ( renderer )
  2325.         {
  2326.           error = renderer->render( renderer, slot, render_mode, NULL );
  2327.           if ( !error ||
  2328.                FT_ERROR_BASE( error ) != FT_Err_Cannot_Render_Glyph )
  2329.             break;
  2330.  
  2331.           /* FT_Err_Cannot_Render_Glyph is returned if the render mode   */
  2332.           /* is unsupported by the current renderer for this glyph image */
  2333.           /* format.                                                     */
  2334.  
  2335.           /* now, look for another renderer that supports the same */
  2336.           /* format.                                               */
  2337.           renderer = FT_Lookup_Renderer( library, slot->format, &node );
  2338.           update   = 1;
  2339.         }
  2340.  
  2341.         /* if we changed the current renderer for the glyph image format */
  2342.         /* we need to select it as the next current one                  */
  2343.         if ( !error && update && renderer )
  2344.           FT_Set_Renderer( library, renderer, 0, 0 );
  2345.       }
  2346.     }
  2347.  
  2348.     return error;
  2349.   }
  2350.  
  2351.  
  2352.   /* documentation is in freetype.h */
  2353.  
  2354.   FT_EXPORT_DEF( FT_Error )
  2355.   FT_Render_Glyph( FT_GlyphSlot  slot,
  2356.                    FT_UInt       render_mode )
  2357.   {
  2358.     FT_Library   library;
  2359.  
  2360.  
  2361.     if ( !slot )
  2362.       return FT_Err_Invalid_Argument;
  2363.  
  2364.     library = FT_FACE_LIBRARY( slot->face );
  2365.  
  2366.     return FT_Render_Glyph_Internal( library, slot, render_mode );
  2367.   }
  2368.  
  2369.  
  2370.   /*************************************************************************/
  2371.   /*************************************************************************/
  2372.   /*************************************************************************/
  2373.   /****                                                                 ****/
  2374.   /****                                                                 ****/
  2375.   /****                         M O D U L E S                           ****/
  2376.   /****                                                                 ****/
  2377.   /****                                                                 ****/
  2378.   /*************************************************************************/
  2379.   /*************************************************************************/
  2380.   /*************************************************************************/
  2381.  
  2382.  
  2383.   /*************************************************************************/
  2384.   /*                                                                       */
  2385.   /* <Function>                                                            */
  2386.   /*    Destroy_Module                                                     */
  2387.   /*                                                                       */
  2388.   /* <Description>                                                         */
  2389.   /*    Destroys a given module object.  For drivers, this also destroys   */
  2390.   /*    all child faces.                                                   */
  2391.   /*                                                                       */
  2392.   /* <InOut>                                                               */
  2393.   /*     module :: A handle to the target driver object.                   */
  2394.   /*                                                                       */
  2395.   /* <Note>                                                                */
  2396.   /*     The driver _must_ be LOCKED!                                      */
  2397.   /*                                                                       */
  2398.   static void
  2399.   Destroy_Module( FT_Module  module )
  2400.   {
  2401.     FT_Memory         memory  = module->memory;
  2402.     FT_Module_Class*  clazz   = module->clazz;
  2403.     FT_Library        library = module->library;
  2404.  
  2405.  
  2406.     /* finalize client-data - before anything else */
  2407.     if ( module->generic.finalizer )
  2408.       module->generic.finalizer( module );
  2409.  
  2410.     if ( library && library->auto_hinter == module )
  2411.       library->auto_hinter = 0;
  2412.  
  2413.     /* if the module is a renderer */
  2414.     if ( FT_MODULE_IS_RENDERER( module ) )
  2415.       ft_remove_renderer( module );
  2416.  
  2417.     /* if the module is a font driver, add some steps */
  2418.     if ( FT_MODULE_IS_DRIVER( module ) )
  2419.       Destroy_Driver( FT_DRIVER( module ) );
  2420.  
  2421.     /* finalize the module object */
  2422.     if ( clazz->module_done )
  2423.       clazz->module_done( module );
  2424.  
  2425.     /* discard it */
  2426.     FREE( module );
  2427.   }
  2428.  
  2429.  
  2430.   /* documentation is in ftmodule.h */
  2431.  
  2432.   FT_EXPORT_DEF( FT_Error )
  2433.   FT_Add_Module( FT_Library              library,
  2434.                  const FT_Module_Class*  clazz )
  2435.   {
  2436.     FT_Error   error;
  2437.     FT_Memory  memory;
  2438.     FT_Module  module;
  2439.     FT_UInt    nn;
  2440.  
  2441.  
  2442. #define FREETYPE_VER_FIXED  ( ( (FT_Long)FREETYPE_MAJOR << 16 ) | \
  2443.                                 FREETYPE_MINOR                  )
  2444.  
  2445.     if ( !library )
  2446.       return FT_Err_Invalid_Library_Handle;
  2447.  
  2448.     if ( !clazz )
  2449.       return FT_Err_Invalid_Argument;
  2450.  
  2451.     /* check freetype version */
  2452.     if ( clazz->module_requires > FREETYPE_VER_FIXED )
  2453.       return FT_Err_Invalid_Version;
  2454.  
  2455.     /* look for a module with the same name in the library's table */
  2456.     for ( nn = 0; nn < library->num_modules; nn++ )
  2457.     {
  2458.       module = library->modules[nn];
  2459.       if ( strcmp( module->clazz->module_name, clazz->module_name ) == 0 )
  2460.       {
  2461.         /* this installed module has the same name, compare their versions */
  2462.         if ( clazz->module_version <= module->clazz->module_version )
  2463.           return FT_Err_Lower_Module_Version;
  2464.  
  2465.         /* remove the module from our list, then exit the loop to replace */
  2466.         /* it by our new version..                                        */
  2467.         FT_Remove_Module( library, module );
  2468.         break;
  2469.       }
  2470.     }
  2471.  
  2472.     memory = library->memory;
  2473.     error  = FT_Err_Ok;
  2474.  
  2475.     if ( library->num_modules >= FT_MAX_MODULES )
  2476.     {
  2477.       error = FT_Err_Too_Many_Drivers;
  2478.       goto Exit;
  2479.     }
  2480.  
  2481.     /* allocate module object */
  2482.     if ( ALLOC( module,clazz->module_size ) )
  2483.       goto Exit;
  2484.  
  2485.     /* base initialization */
  2486.     module->library = library;
  2487.     module->memory  = memory;
  2488.     module->clazz   = (FT_Module_Class*)clazz;
  2489.  
  2490.     /* check whether the module is a renderer - this must be performed */
  2491.     /* before the normal module initialization                         */
  2492.     if ( FT_MODULE_IS_RENDERER( module ) )
  2493.     {
  2494.       /* add to the renderers list */
  2495.       error = ft_add_renderer( module );
  2496.       if ( error )
  2497.         goto Fail;
  2498.     }
  2499.  
  2500.     /* is the module a auto-hinter? */
  2501.     if ( FT_MODULE_IS_HINTER( module ) )
  2502.       library->auto_hinter = module;
  2503.  
  2504.     /* if the module is a font driver */
  2505.     if ( FT_MODULE_IS_DRIVER( module ) )
  2506.     {
  2507.       /* allocate glyph loader if needed */
  2508.       FT_Driver   driver = FT_DRIVER( module );
  2509.  
  2510.  
  2511.       driver->clazz = (FT_Driver_Class*)module->clazz;
  2512.       if ( FT_DRIVER_USES_OUTLINES( driver ) )
  2513.       {
  2514.         error = FT_GlyphLoader_New( memory, &driver->glyph_loader );
  2515.         if ( error )
  2516.           goto Fail;
  2517.       }
  2518.     }
  2519.  
  2520.     if ( clazz->module_init )
  2521.     {
  2522.       error = clazz->module_init( module );
  2523.       if ( error )
  2524.         goto Fail;
  2525.     }
  2526.  
  2527.     /* add module to the library's table */
  2528.     library->modules[library->num_modules++] = module;
  2529.  
  2530.   Exit:
  2531.     return error;
  2532.  
  2533.   Fail:
  2534.     if ( FT_MODULE_IS_DRIVER( module ) )
  2535.     {
  2536.       FT_Driver  driver = FT_DRIVER( module );
  2537.  
  2538.  
  2539.       if ( FT_DRIVER_USES_OUTLINES( driver ) )
  2540.         FT_GlyphLoader_Done( driver->glyph_loader );
  2541.     }
  2542.  
  2543.     if ( FT_MODULE_IS_RENDERER( module ) )
  2544.     {
  2545.       FT_Renderer  renderer = FT_RENDERER( module );
  2546.  
  2547.  
  2548.       if ( renderer->raster )
  2549.         renderer->clazz->raster_class->raster_done( renderer->raster );
  2550.     }
  2551.  
  2552.     FREE( module );
  2553.     goto Exit;
  2554.   }
  2555.  
  2556.  
  2557.   /* documentation is in ftmodule.h */
  2558.  
  2559.   FT_EXPORT_DEF( FT_Module )
  2560.   FT_Get_Module( FT_Library   library,
  2561.                  const char*  module_name )
  2562.   {
  2563.     FT_Module   result = 0;
  2564.     FT_Module*  cur;
  2565.     FT_Module*  limit;
  2566.  
  2567.  
  2568.     if ( !library || !module_name )
  2569.       return result;
  2570.  
  2571.     cur   = library->modules;
  2572.     limit = cur + library->num_modules;
  2573.  
  2574.     for ( ; cur < limit; cur++ )
  2575.       if ( strcmp( cur[0]->clazz->module_name, module_name ) == 0 )
  2576.       {
  2577.         result = cur[0];
  2578.         break;
  2579.       }
  2580.  
  2581.     return result;
  2582.   }
  2583.  
  2584.  
  2585.   /* documentation is in ftobjs.h */
  2586.  
  2587.   FT_BASE_DEF( const void* )
  2588.   FT_Get_Module_Interface( FT_Library   library,
  2589.                            const char*  mod_name )
  2590.   {
  2591.     FT_Module  module;
  2592.  
  2593.  
  2594.     /* test for valid `library' delayed to FT_Get_Module() */
  2595.  
  2596.     module = FT_Get_Module( library, mod_name );
  2597.  
  2598.     return module ? module->clazz->module_interface : 0;
  2599.   }
  2600.  
  2601.  
  2602.   /* documentation is in ftmodule.h */
  2603.  
  2604.   FT_EXPORT_DEF( FT_Error )
  2605.   FT_Remove_Module( FT_Library  library,
  2606.                     FT_Module   module )
  2607.   {
  2608.     /* try to find the module from the table, then remove it from there */
  2609.  
  2610.     if ( !library )
  2611.       return FT_Err_Invalid_Library_Handle;
  2612.  
  2613.     if ( module )
  2614.     {
  2615.       FT_Module*  cur   = library->modules;
  2616.       FT_Module*  limit = cur + library->num_modules;
  2617.  
  2618.  
  2619.       for ( ; cur < limit; cur++ )
  2620.       {
  2621.         if ( cur[0] == module )
  2622.         {
  2623.           /* remove it from the table */
  2624.           library->num_modules--;
  2625.           limit--;
  2626.           while ( cur < limit )
  2627.           {
  2628.             cur[0] = cur[1];
  2629.             cur++;
  2630.           }
  2631.           limit[0] = 0;
  2632.  
  2633.           /* destroy the module */
  2634.           Destroy_Module( module );
  2635.  
  2636.           return FT_Err_Ok;
  2637.         }
  2638.       }
  2639.     }
  2640.     return FT_Err_Invalid_Driver_Handle;
  2641.   }
  2642.  
  2643.  
  2644.   /*************************************************************************/
  2645.   /*************************************************************************/
  2646.   /*************************************************************************/
  2647.   /****                                                                 ****/
  2648.   /****                                                                 ****/
  2649.   /****                         L I B R A R Y                           ****/
  2650.   /****                                                                 ****/
  2651.   /****                                                                 ****/
  2652.   /*************************************************************************/
  2653.   /*************************************************************************/
  2654.   /*************************************************************************/
  2655.  
  2656.  
  2657.   /* documentation is in ftmodule.h */
  2658.  
  2659.   FT_EXPORT_DEF( FT_Error )
  2660.   FT_New_Library( FT_Memory    memory,
  2661.                   FT_Library  *alibrary )
  2662.   {
  2663.     FT_Library  library = 0;
  2664.     FT_Error    error;
  2665.  
  2666.  
  2667.     if ( !memory )
  2668.       return FT_Err_Invalid_Argument;
  2669.  
  2670.     /* first of all, allocate the library object */
  2671.     if ( ALLOC( library, sizeof ( *library ) ) )
  2672.       return error;
  2673.  
  2674.     library->memory        = memory;
  2675.  
  2676.     /* allocate the render pool */
  2677.     library->raster_pool_size = FT_RENDER_POOL_SIZE;
  2678.     if ( ALLOC( library->raster_pool, FT_RENDER_POOL_SIZE ) )
  2679.       goto Fail;
  2680.  
  2681.     /* That's ok now */
  2682.     *alibrary = library;
  2683.  
  2684.     return FT_Err_Ok;
  2685.  
  2686.   Fail:
  2687.     FREE( library );
  2688.     return error;
  2689.   }
  2690.  
  2691.  
  2692.   /* documentation is in freetype.h */
  2693.   
  2694.   FT_EXPORT_DEF( void )
  2695.   FT_Library_Version( FT_Library   library,
  2696.                       FT_Int      *amajor,
  2697.                       FT_Int      *aminor,
  2698.                       FT_Int      *apatch )
  2699.   {
  2700.     FT_Int  major = 0;
  2701.     FT_Int  minor = 0;
  2702.     FT_Int  patch = 0;
  2703.  
  2704.     
  2705.     if ( library )
  2706.     {
  2707.       major = library->version_major;
  2708.       minor = library->version_minor;
  2709.       patch = library->version_patch;
  2710.     }
  2711.     
  2712.     if ( *amajor )
  2713.       *amajor = major;
  2714.       
  2715.     if ( *aminor )
  2716.       *aminor = minor;
  2717.       
  2718.     if ( *apatch )
  2719.       *apatch = patch;
  2720.   }                      
  2721.  
  2722.  
  2723.   /* documentation is in ftmodule.h */
  2724.  
  2725.   FT_EXPORT_DEF( FT_Error )
  2726.   FT_Done_Library( FT_Library  library )
  2727.   {
  2728.     FT_Memory  memory;
  2729.  
  2730.  
  2731.     if ( !library )
  2732.       return FT_Err_Invalid_Library_Handle;
  2733.  
  2734.     memory = library->memory;
  2735.  
  2736.     /* Discard client-data */
  2737.     if ( library->generic.finalizer )
  2738.       library->generic.finalizer( library );
  2739.  
  2740.     /* Close all modules in the library */
  2741. #if 1
  2742.     while ( library->num_modules > 0 )
  2743.       FT_Remove_Module( library, library->modules[0] );
  2744. #else
  2745.     {
  2746.       FT_UInt  n;
  2747.  
  2748.  
  2749.       for ( n = 0; n < library->num_modules; n++ )
  2750.       {
  2751.         FT_Module  module = library->modules[n];
  2752.  
  2753.  
  2754.         if ( module )
  2755.         {
  2756.           Destroy_Module( module );
  2757.           library->modules[n] = 0;
  2758.         }
  2759.       }
  2760.     }
  2761. #endif
  2762.  
  2763.     /* Destroy raster objects */
  2764.     FREE( library->raster_pool );
  2765.     library->raster_pool_size = 0;
  2766.  
  2767.     FREE( library );
  2768.     return FT_Err_Ok;
  2769.   }
  2770.  
  2771.  
  2772.   /* documentation is in ftmodule.h */
  2773.  
  2774.   FT_EXPORT_DEF( void )
  2775.   FT_Set_Debug_Hook( FT_Library         library,
  2776.                      FT_UInt            hook_index,
  2777.                      FT_DebugHook_Func  debug_hook )
  2778.   {
  2779.     if ( library && debug_hook &&
  2780.          hook_index <
  2781.            ( sizeof ( library->debug_hooks ) / sizeof ( void* ) ) )
  2782.       library->debug_hooks[hook_index] = debug_hook;
  2783.   }
  2784.  
  2785.  
  2786. /* END */
  2787.